#include "stdafx.h"
#include "HttpGet.h"
#include "DlgSimpleDownload.h"
#include "DlgSetProxy.h"
#include "MD5.h"


BEGIN_MESSAGE_MAP(DlgSimpleDownload, CDialog)
    ON_COMMAND(IDC_SAVE_TO_FILE, OnSaveToFile)
    ON_COMMAND(IDC_SET_PROXY, OnSetProxy)
    ON_MESSAGE(UIS_WM_UPDATE_PROGRESS_UI, OnUpdateProgressUI)
END_MESSAGE_MAP()


//-------------------------------------------------------------------------------------
BOOL DlgSimpleDownload::OnInitDialog()
{
    ClearOutputText() ;

    // set init value
    SetDlgItemText(IDC_EDIT_START, _T("0")) ;
    SetDlgItemText(IDC_EDIT_AGENT, HTTP_SEND_HEADER().m_user_agent) ;
    CString   s ;
    s += _T("Referer: http://www.UIStone.com/\r\n") ;
    s += _T("Accept: */*\r\n") ;
    SetDlgItemText(IDC_EDIT_FIELD, s) ;

    return CDialog::OnInitDialog() ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::ClearOutputText()
{
    SetDlgItemText(IDC_TEXT_STATUS, _T("")) ;
    SetDlgItemText(IDC_TEXT_TOTAL, _T("")) ;
    SetDlgItemText(IDC_TEXT_DOWNLOAD, _T("")) ;
    SetDlgItemText(IDC_TEXT_CURRENT_SPEED, _T("")) ;
    SetDlgItemText(IDC_TEXT_AVERAGE_SPEED, _T("")) ;
    SetDlgItemText(IDC_TEXT_ELAPSE_TIME, _T("")) ;
    SetDlgItemText(IDC_TEXT_MD5, _T("")) ;
    SetDlgItemText(IDC_TEXT_SEND_HEADER, _T("")) ;
    SetDlgItemText(IDC_TEXT_RESPONSE_HEADER, _T("")) ;
    SendDlgItemMessage(IDC_DOWN_PROGRESS, PBM_SETRANGE32, 0, 100) ;
    SendDlgItemMessage(IDC_DOWN_PROGRESS, PBM_SETPOS, 0) ;
    ::EnableWindow(::GetDlgItem(m_hWnd, IDC_SAVE_TO_FILE), FALSE) ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::OnOK()
{
    DeleteAllDownload() ;
    { CFile   f (m_tmp_data_file, CFile::modeCreate); } // clear file

    // is stop
    CString   btn_txt ;
    GetDlgItemText(IDOK, btn_txt) ;
    if (btn_txt == _T("Stop"))
    {
        SetDlgItemText (IDC_TEXT_STATUS, _T("User Stoped")) ;
        SetDlgItemText (IDOK, _T("Download")) ;
        return ;
    }

    CString   sUrl, sAgent, sStart, sField ;
    GetDlgItemText(IDC_EDIT_URL, sUrl) ;
    GetDlgItemText(IDC_EDIT_AGENT, sAgent) ;
    GetDlgItemText(IDC_EDIT_START, sStart) ;
    GetDlgItemText(IDC_EDIT_FIELD, sField) ;

    if (!UrlIs(sUrl, URLIS_URL))
    {
        EDITBALLOONTIP   t ;
        t.cbStruct = sizeof(t) ;
        t.pszTitle = L"error" ;
        t.pszText = L"This url is not valid!" ;
        t.ttiIcon = TTI_ERROR ;
        SendDlgItemMessage (IDC_EDIT_URL, EM_SHOWBALLOONTIP, 0, (LPARAM)&t) ;
        return ;
    }

    ClearOutputText() ;
    SetDlgItemText(IDC_TEXT_STATUS, _T("Connecting")) ;

    HTTP_SEND_HEADER   ht ;
    ht.m_url = sUrl ;
    ht.m_user_agent = sAgent ;
    if (sStart.GetLength())
        ht.m_start = _ttoi(sStart) ;
    ht.m_header = sField ;
    ht.m_proxy_ip = DlgSetProxy::s_task.m_proxy_ip ;
    ht.m_proxy_port = DlgSetProxy::s_task.m_proxy_port ;
    ht.m_proxy_username = DlgSetProxy::s_task.m_proxy_username ;
    ht.m_proxy_password = DlgSetProxy::s_task.m_proxy_password ;

    int   nTaskID = AddDownload(ht) ;
    m_monitor.reset (new CDownloadMonitor(m_hWnd, nTaskID)) ;

    SetDlgItemText(IDOK, _T("Stop")) ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::OnSaveToFile()
{
    CFileDialog   dlg (FALSE) ;
    if (dlg.DoModal() == IDOK)
    {
        CopyFile (m_tmp_data_file, dlg.GetPathName(), FALSE) ;
    }
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::OnSetProxy()
{
    DlgSetProxy   dlg ;
    dlg.DoModal() ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::OnAfterDownloadConnected (FCHttpDownload* pTask)
{
    const HTTP_RESPONSE_INFO   & resp = pTask->GetResponseInfo() ;

    if (resp.m_status_code == 0)
    {
        SetDlgItemText (IDC_TEXT_STATUS, _T("Can't Connect to server")) ;
        DeleteDownload (pTask->GetTaskID()) ;
        SetDlgItemText (IDOK, _T("Download")) ;
        return ;
    }

    // show header
    SetDlgItemText(IDC_TEXT_SEND_HEADER, resp.QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS)) ;
    SetDlgItemText(IDC_TEXT_RESPONSE_HEADER, resp.QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF)) ;

    // change status
    SetDlgItemText (IDC_TEXT_STATUS, _T("Reading")) ;

    // total length
    CString   s ;
    int   nTotal = resp.m_content_length ;
    if (nTotal)
    {
        s.Format(_T("%d Kb"), (int)ceil(nTotal/1024.0)) ;
    }
    else
    {
        s = _T("Unknow") ;
    }
    SetDlgItemText(IDC_TEXT_TOTAL, s) ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::AcceptReceivedData (FCHttpDownload* pTask)
{
    BYTE   * p ;
    int    n ;
    pTask->PopReceived(p, n) ;
    if (p)
    {
        CFile   f (m_tmp_data_file, CFile::modeNoTruncate|CFile::modeWrite|CFile::shareDenyWrite) ;
        f.SeekToEnd() ;
        f.Write (p, n) ;
        delete[] p ;
    }
}
//-------------------------------------------------------------------------------------
LRESULT DlgSimpleDownload::OnUpdateProgressUI (WPARAM wParam, LPARAM lParam)
{
    if (!m_monitor.get())
        return 0 ;

    FCHttpDownload   * p = FindDownload((int)wParam) ;
    if (!p)
    {
        m_monitor.reset() ;
        return 0 ;
    }

    AcceptReceivedData(p) ;

    CString   s ;

    // elapse time
    s.Format(_T("%d Second"), m_monitor->GetElapseTime()/1000) ;
    SetDlgItemText (IDC_TEXT_ELAPSE_TIME, s) ;

    // download
    int   nDownload = p->GetDownloadByte() ;
    int   nTotal = p->GetResponseInfo().m_content_length ;
    if (nTotal)
    {
        int   nPercent = (int)(100 * (INT64)nDownload / nTotal) ;
        s.Format(_T("%d Kb (%d%%)"), (int)ceil(nDownload/1024.0), nPercent) ;
        SendDlgItemMessage (IDC_DOWN_PROGRESS, PBM_SETPOS, nPercent) ;
    }
    else
    {
        s.Format(_T("%d Kb"), (int)ceil(nDownload/1024.0)) ;
    }
    SetDlgItemText (IDC_TEXT_DOWNLOAD, s) ;

    // current speed
    s.Format(_T("%d Kb / S"), (int)ceil(p->GetCurrentSpeed()/1024.0)) ;
    SetDlgItemText (IDC_TEXT_CURRENT_SPEED, s) ;

    // average speed
    s.Format(_T("%d Kb / S"), (int)ceil(p->GetAverageSpeed()/1024.0)) ;
    SetDlgItemText (IDC_TEXT_AVERAGE_SPEED, s) ;
    return 0 ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::FinishUpdateStatus (FCHttpDownload* pTask)
{
    const HTTP_RESPONSE_INFO   & resp = pTask->GetResponseInfo() ;
    int   nDownload = (int)FCFileEx::GetSize(m_tmp_data_file) ;

    CString   s ;
    switch (resp.m_status_code)
    {
         case HTTP_STATUS_OK :
         case HTTP_STATUS_PARTIAL_CONTENT :
             if (resp.m_content_length)
             {
                 if (resp.m_content_length == nDownload)
                     s = _T("Success") ;
                 else
                     s = _T("Read Error") ;
             }
             else
             {
                 if (resp.m_final_read_result)
                     s = _T("Success") ;
                 else
                     s = _T("Read Error") ;
             }

             // range request
             if (pTask->GetSendHeader().m_start && (resp.m_status_code == HTTP_STATUS_OK))
             {
                 s += _T(" ( not support range )") ;
             }
             break;

        case HTTP_STATUS_NOT_FOUND :
            s = _T("404 error : Not Found") ;
            break;

        case HTTP_STATUS_FORBIDDEN :
            s = _T("403 error : Forbidden") ;
            break;

        case HTTP_STATUS_PROXY_AUTH_REQ :
            s = _T("407 error : Proxy Authentication Required") ;
            break;

        default :
            {
                CString   tts ;
                tts.Format(_T("Download Error, status code : %d"), resp.m_status_code) ;
                s = tts ;
            }
            break;
    }

    SetDlgItemText (IDC_TEXT_STATUS, s) ;

    // calculate MD5
    CString  sMD5 ;
    void     * p ;
    int      n ;
    FCFileEx::Read (m_tmp_data_file, p, n) ;
    if (p)
    {
        sMD5 = FCCrypt::Get_MD5(p, n) ;
        delete[] p ;
    }
    SetDlgItemText (IDC_TEXT_MD5, sMD5) ;
}
//-------------------------------------------------------------------------------------
void DlgSimpleDownload::OnAfterDownloadFinish (FCHttpDownload* pTask)
{
    OnUpdateProgressUI ((WPARAM)pTask->GetTaskID(), 0) ;

    FinishUpdateStatus (pTask) ;
    SendDlgItemMessage(IDC_DOWN_PROGRESS, PBM_SETPOS, 100) ;

    SetDlgItemText (IDOK, _T("Download")) ;
    ::EnableWindow(::GetDlgItem(m_hWnd, IDC_SAVE_TO_FILE), TRUE) ;
}
//-------------------------------------------------------------------------------------
